package database

import (
	"go_redis_service/interface/IResp"
	"go_redis_service/lib/wildcard"
	"go_redis_service/resp/reply"
	"strconv"
)

func init() {
	RegisterCommand("del", execDel, -2)
	RegisterCommand("exists", execExists, -2)
	RegisterCommand("flushdb", execFlushDB, -1)
	RegisterCommand("type", execType, 2)
	RegisterCommand("rename", execRename, 3)
	RegisterCommand("RenameNx", execRenameNx, 3)
	RegisterCommand("Keys", execKeys, 2)
	RegisterCommand("llkey", execRandomKeys, 2)
}

// execDel
// @Description: 批量删除
// @param db
// @param args
// @return IResp.Reply
func execDel(db *DB, args [][]byte) IResp.Reply {
	keys := make([]string, len(args))
	for i, v := range args {
		keys[i] = string(v)
	}
	deleted := db.Removes(keys...)
	return reply.NewIntReply(int64(deleted))
}

// execExists
// @Description: 存在查看
// @param db
// @param args
// @return IResp.Reply
func execExists(db *DB, args [][]byte) IResp.Reply {
	result := int64(0)
	for _, arg := range args {
		key := string(arg)
		_, exists := db.GetEntity(key)
		if exists {
			result++
		}
	}
	return reply.NewIntReply(result)
}

// execFlush
// @Description: 清表
// @param db
// @param args
// @return IResp.Reply
func execFlushDB(db *DB, args [][]byte) IResp.Reply {
	db.Flush()
	return reply.NewOkReply()
}

// execType
// @Description: 检查key 对应value类型
// @param db
// @param args
// @return IResp.Reply
func execType(db *DB, args [][]byte) IResp.Reply {
	key := string(args[0])
	entity, exists := db.GetEntity(key)
	if !exists {
		return reply.NewStatusReply("none")
	}
	switch entity.Data.(type) {
	case []byte:
		return reply.NewStatusReply("string")
	}
	return &reply.UnknownErrReply{}
}

func execRename(db *DB, args [][]byte) IResp.Reply {
	if len(args) != 2 {
		return reply.NewStadardErrReply("Err args for command 'rename'")
	}
	src := string(args[0])
	dest := string(args[1])
	entity, exists := db.GetEntity(src)
	if !exists {
		return reply.NewStadardErrReply("no kes: " + src)
	}
	db.PutEntity(dest, entity)
	db.Remove(src)
	return reply.NewOkReply()
}

// execRenameNx
// @Description: key1 -> key2 key2不存在则将key1改成key2
// @param db
// @param args
// @return IResp.Reply
func execRenameNx(db *DB, args [][]byte) IResp.Reply {
	if len(args) != 2 {
		return reply.NewStadardErrReply("Err args for command 'execRenameNx'")
	}
	src := string(args[0])
	dest := string(args[1])
	_, exists := db.GetEntity(dest)
	if exists {
		return reply.NewIntReply(0)
	}
	entity, ok := db.GetEntity(src)
	if !ok {
		return reply.NewStadardErrReply("no such key")
	}
	db.Removes(src, dest)
	db.PutEntity(dest, entity)
	return reply.NewIntReply(1)
}

// execKeys
// @Description: 根据通配符返回keys
// @param db
// @param args
// @return IResp.Reply
func execKeys(db *DB, args [][]byte) IResp.Reply {
	pattern := wildcard.CompilePattern(string(args[0]))
	result := make([][]byte, 0)
	db.data.ForEach(func(key string, val interface{}) bool {
		if pattern.IsMatch(key) {
			result = append(result, []byte(key))
		}
		return true
	})
	return reply.NewMultiBulkReply(result)
}

func execRandomKeys(db *DB, args [][]byte) IResp.Reply {
	num, _ := strconv.ParseInt(string(args[0]), 10, 64)
	list := db.GetKeyList(int(num))
	result := make([][]byte, len(list))
	for i, item := range list {
		result[i] = []byte(item)
	}
	return reply.NewMultiBulkReply(result)
}
